package pl.edu.agh.lab2.sr.server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import pl.edu.agh.lab2.sr.beans.GameAlreadyCreatedException;
import pl.edu.agh.lab2.sr.beans.InvalidUserException;
import pl.edu.agh.lab2.sr.game.BattleshipGame;
import pl.edu.agh.lab2.sr.game.IBattleshipGame;
import pl.edu.agh.lab2.sr.player.IPlayer;

public class BattleshipServer  implements IBattleshipServer {

	private int gameIdIterator;
	private List<IPlayer> registeredPlayers;
	private Map<IPlayer, IBattleshipGame> createdGames;

	public BattleshipServer() throws RemoteException{
		registeredPlayers = new ArrayList<IPlayer>();
		createdGames = new HashMap<IPlayer, IBattleshipGame>();
		gameIdIterator = 1;
	}

	@Override
	public void register(IPlayer player) throws RemoteException,
			InvalidUserException {

		if (!registeredPlayers.contains(player)) {
			registeredPlayers.add(player);
			System.out.println("[INFO] registered player: " + player.getNick());
		} else {
			System.out.println("[INFO] registering player failed: "
					+ player.getNick());
			throw new InvalidUserException("Player already registered: "
					+ player.getNick());
		}
	}

	@Override
	public void unregister(IPlayer player) throws RemoteException,
			InvalidUserException {

		try {
			boolean removed = registeredPlayers.remove(player);
			if (!removed) {
				throw new InvalidUserException("error when removing player: "
						+ player.getNick());

			}
			System.out.println("[INFO] unregistered player: "
					+ player.getNick());

		} catch (Exception e) {
			throw new InvalidUserException(e.getMessage());
		}

	}

	@Override
	public List<String> getRegisteredPlayers() throws RemoteException {
		List<String> retList = new ArrayList<String>();
		for (IPlayer player : registeredPlayers) {
			retList.add(player.toString());
		}
		return retList;
	}

	@Override
	public int createBattleshipGame(IPlayer player)
			throws RemoteException, GameAlreadyCreatedException,
			InvalidUserException {
		if (!registeredPlayers.contains(player)) {
			System.err.println("Player not registered");
			throw new InvalidUserException("Player not registered");
		}

		if (createdGames.containsKey(player)) {
			System.err.println("Game already created");
			throw new GameAlreadyCreatedException("game already created");
		}
		IBattleshipGame game = new BattleshipGame(player, gameIdIterator);
		createdGames.put(player, game);
		System.out.println("created game: " + gameIdIterator);
		gameIdIterator++;
		return gameIdIterator - 1;
	}

	@Override
	public void removeGame(IPlayer player) {
		createdGames.remove(player);
	}

	@Override
	public List<String> getGamesList() throws RemoteException {
		List<String> retList = new ArrayList<String>();
		for (IPlayer player : createdGames.keySet()) {
			retList.add("id: " + createdGames.get(player).getId()
					+ ", player: " + player);
		}

		return retList;
	}

	@Override
	public IBattleshipGame join(IPlayer newPlayer, int gameId) throws RemoteException,
			InvalidUserException {

		if (!registeredPlayers.contains(newPlayer)) {
			System.err.println("Player not registered");
			throw new InvalidUserException("Player not registered");
		}

		IBattleshipGame game = getGameById(gameId);

		IPlayer player1 = game.getPlayer1();
		IPlayer player2 = game.getPlayer2();

		if (player2 != null) {
			throw new IllegalStateException("player2 already assigned");
		}
		if (newPlayer == null) {
			throw new InvalidUserException("null instead of player");
		}
		if (newPlayer == player1) {
			throw new InvalidUserException(
					"player already assigned to that game");
		}

		if (player2 == null) {
			game.addSecondPlayer(newPlayer);
			
		}
		System.out.println("[S] player joined game: " + newPlayer + " " + gameId);
		return game;
	}

	@Override
	public IBattleshipGame getGameById(int gameId) throws RemoteException {
		for (IPlayer player : createdGames.keySet()) {
			IBattleshipGame game = createdGames.get(player);
			if (game.getId() == gameId) {
				return game;
			}
		}
		throw new IllegalArgumentException("Game does not exist: " + gameId);
	}


}
